package andev.axplorer;

import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.ServiceConnection;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.text.format.Formatter;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Adapter;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import andev.aandroidlib.activity.AActivity;
import andev.aandroidlib.util.FileOperator;
import andev.aandroidlib.view.MarqueeTextView;
import andev.axplorer.FileWatcher.ImageFileWatcher;
import andev.axplorer.FileWatcher.TextFileWatcher;
import andev.axplorer.FileWatcher.VideoFileWatcher;
import andev.axplorer.Menu.RightMenu;
import andev.axplorer.Service.CrawlDirService;
import andev.axplorer.Tiles.TilesAdapter;
import andev.axplorer.Tiles.TilesAdapterStorage;
import andev.axplorer.Tiles.TilesLayout;
import andev.axplorer.Tiles.TilesLayoutStorage;

public class MainActivity extends AActivity implements View.OnClickListener, DialogInterface.OnClickListener, ServiceConnection {
    public static ArrayList<String> filePathHistory = new ArrayList<>();
    public static String pathNow;
    private static boolean bFirstCreate = true;
    private static int thumbnailW;
    public ImageButton ib_back, ib_forward;
    public ImageButton ib_close, ib_min;
    private GridView file_grid;
    private MarqueeTextView tv_file_name2;
    private TextView tv_file_type;
    private GestureDetector gestureDetector;
    private ImageView iv_search, detail_icon;
    private EditText et_search;
    private ProgressBar loadingPB;
    private ArrayList<Map<String, Object>> file_grid_AdapterData = new ArrayList<>();
    private boolean bSearching = false;
    private Handler loadingHandler;

    public static void addPathNow(String path) {
        pathNow = path;
        filePathHistory.add(path);
    }

    public static void ResetFilePathHistory() {
        filePathHistory.clear();
        addPathNow("start");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        InitActionBar();
        file_grid = (GridView) findViewById(R.id.file_grid);

        ib_back = (ImageButton) findViewById(R.id.ib_back);
        ib_forward = (ImageButton) findViewById(R.id.ib_forward);
        ib_back.setOnClickListener(this);
        ib_forward.setOnClickListener(this);
        ib_forward.setImageResource(R.mipmap.ic_window_forward_disable);
        ib_forward.setClickable(false);

        ib_close = (ImageButton) findViewById(R.id.ib_close);
        ib_min = (ImageButton) findViewById(R.id.ib_min);
        ib_close.setOnClickListener(this);
        ib_min.setOnClickListener(this);

        iv_search = (ImageView) findViewById(R.id.iv_search);
        iv_search.setOnClickListener(this);
        detail_icon = (ImageView) findViewById(R.id.detail_icon);
        et_search = (EditText) findViewById(R.id.et_search);

        tv_file_name2 = (MarqueeTextView) findViewById(R.id.tv_file_name2);
        tv_file_name2.startMarquee(true);
        tv_file_type = (TextView) findViewById(R.id.tv_file_type);

        loadingPB = (ProgressBar) findViewById(R.id.loadingPB);
        loadingHandler = new Handler();

        //初始化所有缩略图大小
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.mipmap.ic_tile_folder, options);
        thumbnailW = options.outWidth;

        gestureDetector = new GestureDetector(this,
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2,
                                           float velocityX, float velocityY) {
                        if (Math.abs(velocityX) > Math.abs(velocityY)) {
                            if (velocityX > 0.6) {
                                operationForward();
                            }
                            if (velocityX < -0.6) {
                                operationBack();
                            }
                        }
                        return super.onFling(e1, e2, velocityX, velocityY);
                    }

                    @Override
                    public void onLongPress(MotionEvent e) {
                        RightMenu.showRightMenu(file_grid, (int) e.getX(), (int) e.getY());
                        super.onLongPress(e);
                    }

                    @Override
                    public boolean onDown(MotionEvent e) {
                        hideKeyboard(true);
                        RightMenu.cancelRightMenu();
                        return super.onDown(e);
                    }
                });
        file_grid.setOnTouchListener(
                new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if (event.getAction() == MotionEvent.ACTION_DOWN) {
                            v.performClick();
                        }
                        return gestureDetector.onTouchEvent(event);
                    }
                });


        if (bFirstCreate) {
            ResetFilePathHistory();
            showStorages();
            bFirstCreate = false;
        } else
            refresh();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    public void updateDetailLine() {
        if (TilesLayout.checkedTile == null) {
            int count = file_grid_AdapterData.size();
            tv_file_name2.setText(count + "项");
            tv_file_type.setText("");
            if (pathNow == "start") {
                detail_icon.setImageResource(R.mipmap.ic_launcher);
            } else {
                detail_icon.setImageResource(R.mipmap.ic_tile_folder);
            }
            return;
        } else {
            FileOperator fileOperator = new FileOperator();
            tv_file_name2.setText(TilesLayout.checkedTile.getFileName());
            File file = TilesLayout.checkedTile.getFile();
            long lastModified = file.lastModified();
            String ctime = new SimpleDateFormat("yyyy-MM-dd hh:mm", Locale.getDefault()).format(new Date(lastModified));
            if (file.isFile()) {
                String size = Formatter.formatFileSize(this, fileOperator.getFileSize(file));
                tv_file_type.setText(fileOperator.getFileExtension(file) + " " + size + " 修改于:" + ctime);
            } else {
                tv_file_type.setText(fileOperator.getDirChildCount(file) + "项 修改于:" + ctime);
            }
            detail_icon.setImageBitmap(TilesLayout.checkedTile.getFileIcon());
        }
    }

    private void InitActionBar() {
    }

    private void showStorages() {
        et_search.setText("");
        file_grid_AdapterData.clear();
        file_grid.setNumColumns(2);
        file_grid.setAdapter(new TilesAdapterStorage(MainActivity.this, file_grid_AdapterData));

        ib_back.setImageResource(R.mipmap.ic_window_back_disable);
        ib_back.setClickable(false);

        Map<String, Object> tileStorageMap = new HashMap<>();
        tileStorageMap.put("storageName", "手机存储");
        file_grid_AdapterData.add(tileStorageMap);

        tileStorageMap = new HashMap<>();
        tileStorageMap.put("storageName", Environment.getExternalStorageDirectory().getName());
        file_grid_AdapterData.add(tileStorageMap);

        file_grid.deferNotifyDataSetChanged();

        updateDetailLine();
        updateBackForward();
    }

    public void showFiles(final File[] files) {
        et_search.setText("");
        RightMenu.cancelRightMenu();

        file_grid.setNumColumns(3);
        file_grid_AdapterData.clear();

        Loading();

        loadingHandler.post(new Runnable() {
            @Override
            public void run() {
                for (File e : files) {
                    makeTileAdapter(e);
                }
                file_grid.setAdapter(new TilesAdapter(MainActivity.this, file_grid_AdapterData));
                Loaded();
                TilesLayout.checkedTile = null;
                updateDetailLine();
                updateBackForward();
            }
        });
    }

    public void makeTileAdapter(File file) {
        Map<String, Object> tileMap = new HashMap<>();
        tileMap.put("fileName", file.getName());
        tileMap.put("filePath", file.getAbsolutePath());
        if (file.isDirectory()) {
            tileMap.put("fileIcon", R.mipmap.ic_tile_folder);
        } else {
            switch (new FileOperator().getFileMIME(file)) {
                case "text/plain":
                    tileMap.put("fileIcon", R.mipmap.ic_text_plain);
                    break;
                case "image/bmp":
                case "image/gif":
                case "image/jpeg":
                case "image/png":
                    tileMap.put("fileIcon", FileOperator.getImageThumbnail(file.getAbsolutePath(), thumbnailW, thumbnailW));
                    break;
                case "video/3gpp":
                case "video/x-ms-asf":
                case "video/x-msvideo":
                case "video/vnd.mpegurl":
                case "video/x-m4v":
                case "video/quicktime":
                case "video/mp4":
                case "video/mpeg":
                    tileMap.put("fileIcon", FileOperator.getVideoThumbnail(file.getAbsolutePath(), thumbnailW, thumbnailW));
                    break;
                case "audio/x-mpegurl":
                case "audio/mp4a-latm":
                case "audio/x-mpeg":
                case "audio/mpeg":
                case "audio/x-wav":
                case "audio/x-ms-wma":
                case "audio/x-ms-wmv":
                case "audio/x-pn-realaudio":
                case "audio/ogg":
                    tileMap.put("fileIcon", R.mipmap.ic_audio);
                    break;
                case "application/x-gtar":
                case "application/x-gzip":
                case "application/x-compress":
                case "application/x-7z-compressed":
                case "application/x-zip-compressed":
                case "application/x-compressed":
                case "application/x-tar":
                    tileMap.put("fileIcon", R.mipmap.ic_compressedfile);
                    break;
                case "application/java-archive":
                    tileMap.put("fileIcon", R.mipmap.ic_javafile);
                    break;
                case "application/vnd.android.package-archive":
                    tileMap.put("fileIcon", R.mipmap.ic_apkfile);
                    break;
                default:
                    tileMap.put("fileIcon", R.mipmap.ic_tile_unknowextension);
                    break;
            }
        }
        file_grid_AdapterData.add(tileMap);
    }

    public void updateBackForward() {
        int index = MainActivity.filePathHistory.lastIndexOf(pathNow);
        int finalIndex = filePathHistory.size() - 1;
        if (index > 0) {
            ib_back.setImageResource(R.mipmap.ic_window_back);
            ib_back.setClickable(true);
        }
        if (index == finalIndex) {
            ib_forward.setImageResource(R.mipmap.ic_window_forward_disable);
            ib_forward.setClickable(false);
        } else {
            ib_forward.setImageResource(R.mipmap.ic_window_forward);
            ib_forward.setClickable(true);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ib_back:
                operationBack();
                break;
            case R.id.ib_forward:
                operationForward();
                break;
            case R.id.ib_close:
                System.exit(0);
                break;
            case R.id.ib_min:
                finish();
                break;
            case R.id.iv_search:
                String search = et_search.getText().toString();
                if ("".equals(search.replaceAll("\\s", ""))) return;

                hideKeyboard(true);

                tryDeletePathsBeforeAdd();
                addPathNow("AxplorerSearch:" + search);

                searchFile(search);
                break;
        }
    }

    private void searchFile(String search) {
        if (bSearching) return;
        bSearching = true;
        Loading();
        file_grid_AdapterData.clear();
        file_grid.setNumColumns(3);
        file_grid.setAdapter(new TilesAdapter(this, file_grid_AdapterData));
        final Adapter file_grid_adapter = file_grid.getAdapter();

        updateBackForward();

        if ((search = search.trim()).contains(" ")) {
            search = search.replaceAll(" ", "[^\\\\\\\\/]*");
        }
        final Pattern pattern = Pattern.compile("\\/[^\\/]*" + search + "[^\\/]*\\/?([^\\/]*)");

        final File[] baseDirs;
        String pathBefore = pathNow;
        if (pathNow.contains("AxplorerSearch:"))
            pathBefore = filePathHistory.get(filePathHistory.lastIndexOf(pathNow) - 1);
        if (pathBefore.equals("start"))
            baseDirs = new File[]{Environment.getDataDirectory(), Environment.getDownloadCacheDirectory(), Environment.getRootDirectory(), Environment.getExternalStorageDirectory()};
        else if (pathBefore.equals("手机存储"))
            baseDirs = new File[]{Environment.getDataDirectory(), Environment.getRootDirectory(), Environment.getDownloadCacheDirectory()};
        else if (pathBefore.equals(Environment.getExternalStorageDirectory()))
            baseDirs = new File[]{Environment.getExternalStorageDirectory()};
        else baseDirs = new File[]{new File(pathBefore)};
        new FileOperator().crawlDirs(MainActivity.this, baseDirs, new FileOperator.CrawlListener() {
            @Override
            public boolean onCrawlHandleData(String absolutePath) {
                Matcher matcher = pattern.matcher(absolutePath);
                String finalMatchGroup1 = "";
                if (matcher.find()) {
                    finalMatchGroup1 = matcher.group(1);
                    while (matcher.find()) {
                        finalMatchGroup1 = matcher.group(1);
                    }
                    if (!"".equals(finalMatchGroup1)) {
                        return false;
                    }
                    makeTileAdapter(new File(absolutePath));
                    return true;
                }
                return false;
            }

            @Override
            public void onCrawlHandleUI(String absolutePath) {
                file_grid.deferNotifyDataSetChanged();
                file_grid.setSelection(file_grid_adapter.getCount() - 1);
            }

            @Override
            public void onCrawlEnd() {
                Loaded();
                updateDetailLine();
                file_grid.setSelection(file_grid_adapter.getCount() - 1);
                Toast.makeText(MainActivity.this, "搜索完毕.", Toast.LENGTH_LONG).show();
                bSearching = false;
            }
        });
    }

    public boolean tryDeletePathsBeforeAdd() {
        if (pathNow.contains("AxplorerSearch:")) {
            filePathHistory.remove(pathNow);
            pathNow = filePathHistory.get(filePathHistory.size() - 1);
        }

        int index = filePathHistory.lastIndexOf(pathNow);
        int finalIndex = filePathHistory.size() - 1;

        if (index < finalIndex) {
            for (int i = index + 1; i <= finalIndex; i++) {
                filePathHistory.remove(index + 1);
            }
            return true;
        } else return false;
    }

    public void refresh() {
        if (pathNow.equals("start")) {
            showStorages();
        } else if (pathNow.equals("手机存储")) {
            TilesLayoutStorage.showInternDirectories();
        } else if (pathNow.equals(Environment.getExternalStorageDirectory().toString())) {
            TilesLayoutStorage.showExternDirectories();
        } else if (pathNow.contains("AxplorerSearch:")) {
            et_search.setText(pathNow.replace("AxplorerSearch:", ""));
            searchFile(pathNow.replace("AxplorerSearch:", ""));
        } else {
            File file = new File(pathNow);

            File[] files = file.listFiles();
            showFiles(files);
        }
    }

    private void operationForward() {
        int index = filePathHistory.lastIndexOf(pathNow);
        int size = filePathHistory.size();
        if (index == size - 1) {
            return;
        }
        pathNow = filePathHistory.get(index + 1);
        refresh();
    }

    private void operationBack() {
        int index = filePathHistory.lastIndexOf(pathNow);
        if (index == 0) {
            return;
        }
        pathNow = filePathHistory.get(index - 1);
        refresh();
    }

    public void Loading() {
        loadingPB.setVisibility(FrameLayout.VISIBLE);
    }

    public void Loaded() {
        loadingPB.setVisibility(FrameLayout.INVISIBLE);
    }

    @Override
    public void onBackPressed() {
        if (pathNow.equals("start")) {
            doublePressExit(true);
        } else {
            operationBack();
        }
    }

    public void openFile(File file) {
        FileOperator fileOperator = new FileOperator();
        String MIME = fileOperator.getFileMIME(file);
        Bundle bundle = new Bundle();
        bundle.putSerializable("file", file);
        switch (MIME) {
        /*In some case I don't want to open file by user chosen*/
            case "text/plain":
                goActivity(bundle, TextFileWatcher.class, false);
                break;
            case "video/3gpp":
            case "video/x-ms-asf":
            case "video/x-msvideo":
            case "video/vnd.mpegurl":
            case "video/x-m4v":
            case "video/quicktime":
            case "video/mp4":
            case "video/mpeg":
                goActivity(bundle, VideoFileWatcher.class, false);
                break;
            case "image/bmp":
            case "image/gif":
            case "image/jpeg":
            case "image/png":
                goActivity(bundle, ImageFileWatcher.class, false);
                break;
            default:
                fileOperator.openFile(this, file, MIME);
                break;
        }
    }

    public void deleteFile() {
        if (TilesLayout.checkedTile == null) return;
        AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setTitle("删除提示")
                .setMessage("确定要删除吗？")
                .setPositiveButton("确定", this)
                .setNegativeButton("取消", this)
                .create();
        alertDialog.show();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                Map<String, Object> tileMap = TilesLayout.checkedTile.getTileMap();
                int bResult = new FileOperator().deleteFile(TilesLayout.checkedTile.getFile());
                if (bResult >= FileOperator.SUCCESS) {
                    Toast.makeText(this, "共删除" + bResult + "个文件(夹)", Toast.LENGTH_LONG).show();
                    TilesLayout.checkedTile = null;

                    int position = file_grid_AdapterData.indexOf(tileMap);
                    if (position > 0) position--;
                    file_grid_AdapterData.remove(tileMap);
                    file_grid.setAdapter(new TilesAdapter(this, file_grid_AdapterData));
                    file_grid.setSelection(position);
                } else if (bResult == FileOperator.FILES_NULL_PTR)
                    Toast.makeText(this, "无法删除，需要ROOT权限", Toast.LENGTH_SHORT).show();
                else Toast.makeText(this, "无法删除，文件不存在或被占用", Toast.LENGTH_SHORT).show();
                break;
            case DialogInterface.BUTTON_NEGATIVE:
                dialog.dismiss();
                break;
        }
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        file_grid.setAdapter(new TilesAdapter(MainActivity.this, file_grid_AdapterData));
        final CrawlDirService crawlDirService = ((CrawlDirService.CralDirServiceBinder) service).getCrawlDirService();

        /*loadingHandler.post(new Runnable()
        {
            @Override
            public void run()
            {
                file_grid_AdapterData=crawlDirService.getAdapterData();
                file_grid.deferNotifyDataSetChanged();
                if (crawlDirService.crawlEnd==false)
                    loadingHandler.postDelayed(this, 500);
                else
                {
                    Loaded();
                    unbindService(MainActivity.this);
                    Toast.makeText(MainActivity.this,"搜索完毕，共找到"+file_grid_AdapterData.size()+"项.",Toast.LENGTH_LONG).show();
                }
            }
        });*/
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}
